home *** CD-ROM | disk | FTP | other *** search
/ T&A 2 the Maxx 3 / T and A 2 The Maxx Number 3.iso / viewers / unixview / xgiftar.z / xgiftar / g3.c < prev    next >
C/C++ Source or Header  |  1991-05-20  |  10KB  |  482 lines

  1. /** g3.c - read a Group 3 FAX file and product a bitmap
  2.  **
  3.  ** Adapted from Paul Haeberli's <paul@manray.sgi.com> G3 to Portable Bitmap 
  4.  ** code.
  5.  **
  6.  ** modified by jimf on 09.18.90 to fail on any load error.  this was done
  7.  ** to cut down on the false positives caused by a lack of any read ID
  8.  ** string.  the old errors are currently ifdef'ed out -- if you want 'em
  9.  ** define ALLOW_G3_ERRORS.
  10.  **/
  11.  
  12. /* Edit History
  13.  
  14. 04/15/91   8 nazgul    Sanity check line widths
  15.             Doing a zclose on all failures
  16. 04/14/91   1 schulert    add <sys/types> for SYSV systems
  17. 04/13/91   6 nazgul    Handle reinvocation on the same file
  18. 04/13/91   5 nazgul    Bug fix to retry with bitreversed, and do not double allocate on multiple calls
  19. 04/12/91   4 nazgul    Spot faxes that do not have a 000 header
  20.             Handle faxes that have the bytes in the wrong order
  21. 07/03/90   2 nazgul    Added recovery for premature EOF
  22. */
  23.  
  24. #include <sys/types.h>
  25. #include <sys/file.h>
  26.  
  27. #include "image.h"
  28. #include "g3.h"
  29.  
  30. /* SUPPRESS 530 */
  31. /* SUPPRESS 558 */
  32. /* SUPPRESS 560 */
  33.  
  34. /****
  35.  **
  36.  ** Local defines
  37.  **
  38.  ****/
  39.  
  40. #define BITS_TO_BYTES(bits)    (bits/8)+((bits-((bits/8)*8)?1:0))
  41. #define TABSIZE(tab) (sizeof(tab)/sizeof(struct tableentry))
  42. #ifdef VMS
  43. #define cols vmscols
  44. #endif
  45.  
  46. /****
  47.  **
  48.  ** Local variables
  49.  **
  50.  ****/
  51.  
  52. static int g3_eof = 0;
  53. static int g3_eols;
  54. static int g3_rawzeros;
  55. static int g3_Xrawzeros;
  56. static int    maxlinelen;
  57. static int    rows, cols;
  58. static int g3_error = 0;
  59. static int g3_verb;
  60. static int curbit;
  61.  
  62. #define MAX_ERRORS    20
  63.  
  64. /****
  65.  **
  66.  ** Local tables
  67.  **
  68.  ****/
  69.  
  70. tableentry *whash[HASHSIZE];
  71. tableentry *bhash[HASHSIZE];
  72.  
  73. int    g3_addtohash(hash, te, n, a, b)
  74.     tableentry    *hash[];
  75.     tableentry    *te;
  76.     int    n, a, b;
  77. {
  78.     unsigned int pos;
  79.  
  80.     while (n--) {
  81.         pos = ((te->length+a)*(te->code+b))%HASHSIZE;
  82.         if (hash[pos] != 0) {
  83. #ifdef ALLOW_G3_ERRORS
  84.             fprintf(stderr, "G3: Hash collision during initialization.\n");
  85.             exit(1);
  86. #else
  87.             ++g3_error;
  88.             return(-1);
  89. #endif
  90.             }
  91.         hash[pos] = te;
  92.         te++;
  93.     }
  94. }
  95.  
  96. tableentry    *g3_hashfind(hash, length, code, a, b)
  97.     tableentry    *hash[];
  98.     int    length, code;
  99.     int    a, b;
  100. {
  101.     unsigned int pos;
  102.     tableentry *te;
  103.  
  104.     pos = ((length+a)*(code+b))%HASHSIZE;
  105.     if (pos >= HASHSIZE) {
  106. #ifndef ALLOW_G3_ERRORS
  107.         fprintf(stderr, "G3: Bad hash position, length %d code %d pos %d.\n", 
  108.             length, code, pos);
  109.         exit(2);
  110. #else
  111.         ++g3_error;
  112.         return(NULL);
  113. #endif
  114.         }
  115.     te = hash[pos];
  116.     return ((te && te->length == length && te->code == code) ? te : 0);
  117. }
  118.  
  119. int    g3_getfaxrow(fd, bitrow)
  120.     ZFILE    *fd;
  121.     byte    *bitrow;
  122. {
  123.         int col;
  124.     int curlen, curcode, nextbit;
  125.     int count, color;
  126.     tableentry *te;
  127.  
  128.     /* First make the whole row white... */
  129.     bzero((char *) bitrow, maxlinelen); /* was memset -- jimf 09.11.90 */
  130.  
  131.     col = 0;
  132.     g3_rawzeros = 0;
  133.     curlen = 0;
  134.     curcode = 0;
  135.     color = 1;
  136.     count = 0;
  137.     while (!g3_eof) {
  138.         if (col >= MAXCOLS) {
  139. #ifdef ALLOW_G3_ERRORS
  140.             if (g3_verb) fprintf(stderr, "G3: Input row %d is too long, skipping to EOL.\n", rows);
  141.             g3_skiptoeol(fd);
  142.             ++g3_error;
  143.             return (col); 
  144. #else
  145.             return(-1);
  146. #endif
  147.             }
  148.         do {
  149.             if (g3_eof) return 0;
  150.             if (g3_rawzeros >= 11) {
  151.                 nextbit = g3_rawgetbit(fd);
  152.                 if (nextbit) {
  153.                     if ( col == 0 )
  154.                         /* 6 consecutive EOLs mean end of document */
  155.                         g3_eof = (++g3_eols >= 5);
  156.                     else
  157.                         g3_eols = 0;
  158.  
  159.                     return (col); 
  160.                     }
  161.                 }
  162.             else
  163.                 nextbit = g3_rawgetbit(fd);
  164.  
  165.             curcode = (curcode<<1) + nextbit; 
  166.             curlen++;
  167.             } while (curcode <= 0);
  168.  
  169.         /* No codewords are greater than 13 bytes */
  170.         if (curlen > 13) {
  171. #ifdef ALLOW_G3_ERRORS
  172.             if (g3_verb) fprintf(stderr, "G3: Bad code word at row %d, col %d (len %d code 0x%2.2x), skipping to EOL.\n", rows, col, curlen, curcode );
  173.             g3_skiptoeol(fd);
  174.             ++g3_error;
  175.             return (col);
  176. #else
  177.             return(-1);
  178. #endif
  179.             }
  180.         if (color) {
  181.             /* White codewords are at least 4 bits long */
  182.             if (curlen < 4)
  183.                 continue;
  184.             te = g3_hashfind(whash, curlen, curcode, WHASHA, WHASHB);
  185.             }
  186.         else {
  187.             /* Black codewords are at least 2 bits long */
  188.             if (curlen < 2)
  189.                 continue;
  190.             te = g3_hashfind(bhash, curlen, curcode, BHASHA, BHASHB);
  191.         }
  192.         if (!te)
  193.             continue;
  194.         switch (te->tabid) {
  195.             case TWTABLE:
  196.             case TBTABLE:
  197.                 count += te->count;
  198.                 if (col+count > MAXCOLS) 
  199.                     count = MAXCOLS-col;
  200.                 if (count > 0) {
  201.                     if (color) {
  202.                         col += count;
  203.                         count = 0;
  204.                         }
  205.                     else
  206.                         g3_bitson(bitrow, col, count);
  207.                     }
  208.                 curcode = 0;
  209.                 curlen = 0;
  210.                 color = !color;
  211.                 break;
  212.             case MWTABLE:
  213.             case MBTABLE:
  214.                 count += te->count;
  215.                 curcode = 0;
  216.                 curlen = 0;
  217.                 break;
  218.             case EXTABLE:
  219.                 count += te->count;
  220.                 curcode = 0;
  221.                 curlen = 0;
  222.                 break;
  223.             default:
  224.                 fprintf(stderr, "G3: Bad table id from table entry.\n");
  225. #ifndef ALLOW_G3_ERRORS
  226.                 exit(3);
  227. #else
  228.                 ++g3_error;
  229.                 return(-1);
  230. #endif
  231.             }
  232.         }
  233.     return (0);
  234. }
  235.  
  236. int    g3_skiptoeol(fd)
  237.     ZFILE    *fd;
  238. {
  239.     while (g3_rawzeros<11 && !g3_eof)
  240.         (void) g3_rawgetbit(fd);
  241.     while(!g3_rawgetbit(fd) && !g3_eof);
  242.     return(0);
  243. }
  244.  
  245. int    g3_rawgetbit(fd)
  246.     ZFILE    *fd;
  247. {
  248.     int    b;
  249.     static int    shdata;
  250.  
  251.     if (curbit >= 8) {
  252.         shdata = zgetc(fd);
  253.         if (shdata == EOF) {
  254. #ifdef ALLOW_G3_ERRORS
  255.                 if (g3_verb) fprintf(stderr, "G3: Premature EOF at line %d.\n", rows);
  256.             g3_eols = 5;
  257.             g3_eof = 1;
  258.             ++g3_error;
  259.             return 0;
  260. #else
  261.             return(-1);
  262. #endif
  263.             }
  264.         curbit = 0;
  265.         }
  266.     if (shdata & bmask[curbit]) {
  267.         g3_Xrawzeros = g3_rawzeros;
  268.         g3_rawzeros = 0;
  269.         b = 1;
  270.         }
  271.     else {
  272.         g3_rawzeros++;
  273.         b = 0;
  274.         }
  275.     curbit++;
  276.     return b;
  277. }
  278.  
  279. int    g3_bitson(b, c, n)
  280.     bit    *b;
  281.     int    c, n;
  282. {
  283.     int    i, col;
  284.     bit    *bP;
  285.     static int    bitmask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
  286.  
  287.     bP = b;
  288.     col = c;
  289.     bP+=(c/8);
  290.     i = (c - ((c/8)*8));
  291.     while(col <= (c+n)) { 
  292.         for(;col <= (c+n) && i < 8; i++) {
  293.             *bP |= bitmask[i];
  294.             col++;
  295.             }
  296.         i = 0;
  297.         bP++;
  298.         }
  299.     return(0);
  300. }
  301.  
  302. /* All G3 images begin with a G3 EOL codeword which is eleven binary 0's
  303.  * followed by one binary 1.  There could be up to 15 0' so that the image
  304.  * starts on a char boundary.
  305.  */
  306. /*
  307.  * They are all *supposed* to, but in fact some don't.  In fact pbmtog3 doesn't seem
  308.  * to generate them.  So if that fails, we'll also try reading a line and seeing if
  309.  * we get any errors.  Note that this means we had to move the call to g3_ident
  310.  * to after the hash table init.  -nazgul
  311.  */
  312.  
  313. int    g3_ident(fd)
  314.     ZFILE    *fd;
  315. {
  316.  
  317.     int        ret = 0, col1, col2, i;
  318.     byte    *tmpline;
  319.     int        reverse = 0;
  320.     struct cache    *dataptr;
  321.     int            bufptr;
  322.     
  323.     g3_verb = 0;
  324.     tmpline = (byte *) lmalloc(maxlinelen);
  325.  
  326.     /* In case this got reset by a previous pass through here */
  327.     for (i = 0; i < 8; ++i) {
  328.     bmask[7-i] = 1 << i;
  329.     }
  330.  
  331. tryagain:
  332.     curbit = 8;
  333.     g3_Xrawzeros = 0;
  334.     g3_eof = g3_eols = rows = cols = 0;
  335.     
  336.     /* If we have the zeros we're off to a good start, otherwise, skip some lines */
  337.     for (g3_rawzeros = 0; !g3_rawgetbit(fd) && !g3_eof;);
  338.     if (g3_Xrawzeros >= 11 && g3_Xrawzeros <= 15) {
  339.     fd->dataptr = fd->data;
  340.     fd->bufptr = 0;
  341.     curbit = 8;
  342.     g3_skiptoeol(fd);
  343.     if (!g3_error) g3_skiptoeol(fd);
  344.     if (!g3_error) g3_skiptoeol(fd);
  345.     if (!g3_error) g3_skiptoeol(fd);
  346.     } else ret = 1;
  347.  
  348.     /* Now get two lines and make sure they are the same length.  If not give up.
  349.      * Note that it is possible for this to give false positives (value.o on a Sun IPC
  350.      * did) but it's unlikely enough that I think we're okay.
  351.      */
  352.     
  353.     dataptr = fd->dataptr;
  354.     bufptr = fd->bufptr;
  355.     if (!g3_error) col1 = g3_getfaxrow(fd, tmpline);
  356.     if (!g3_error) col2 = g3_getfaxrow(fd, tmpline);
  357.     if (!g3_error && col1 == col2 && col1 != 0) ret = 1;
  358.     else ret = 0;
  359.     /* if (ret) printf("%d = %d\n", col1, col2); */
  360.     fd->dataptr = dataptr;
  361.     fd->bufptr = bufptr;
  362.     curbit = 8;
  363.  
  364.     /* This bogus hack is to accomodate some fax modems which apparently use a chip
  365.      * with a different byte order.  We simply try again with the table reversed.
  366.      */
  367.     if (!ret && !reverse) {
  368.     rows = cols = g3_error = 0;
  369.     fd->dataptr = fd->data;
  370.     fd->bufptr = 0;
  371.     g3_Xrawzeros = 0;
  372.     for (i = 0; i < 8; ++i) {
  373.         bmask[i] = 1 << i;
  374.     }
  375.     reverse = 1;
  376.     goto tryagain;
  377.     }
  378.     g3_eols = rows = cols = 0;
  379.     lfree(tmpline);
  380.  
  381.     return(ret);
  382. }
  383.  
  384. Image    *g3Load(fullname, name, verbose)
  385.     char    *fullname, *name;
  386.     unsigned int    verbose;
  387. {
  388.  
  389.     ZFILE    *fd;
  390.     Image    *image;
  391.     int i, col;
  392.     byte    *currline;
  393.     static int firstTime = 1;
  394.  
  395.     if ((fd = zopen(fullname)) == NULL)
  396.         return(NULL);
  397.  
  398.     if (firstTime) {
  399.         firstTime = 0;
  400.         
  401.         /* Initialize and load the hash tables */
  402.         for ( i = 0; i < HASHSIZE; ++i )
  403.           whash[i] = bhash[i] = (tableentry *) 0;
  404.         g3_addtohash(whash, twtable, TABSIZE(twtable), WHASHA, WHASHB);
  405.         g3_addtohash(whash, mwtable, TABSIZE(mwtable), WHASHA, WHASHB);
  406.         g3_addtohash(whash, extable, TABSIZE(extable), WHASHA, WHASHB);
  407.         g3_addtohash(bhash, tbtable, TABSIZE(tbtable), BHASHA, BHASHB);
  408.         g3_addtohash(bhash, mbtable, TABSIZE(mbtable), BHASHA, BHASHB);
  409.         g3_addtohash(bhash, extable, TABSIZE(extable), BHASHA, BHASHB);
  410.     }
  411.     
  412.     g3_eof = g3_eols = 0;
  413.     curbit = 8;    /* Reset on multiple reads */
  414.  
  415.     /* Calulate the number of bytes needed for maximum number of columns 
  416.      * (bits), create a temprary storage area for it.
  417.      */
  418.     maxlinelen = BITS_TO_BYTES(MAXCOLS);
  419.  
  420.     if (!g3_ident(fd)) {
  421.         zclose(fd);
  422.         return(NULL);
  423.     }
  424.     g3_verb = verbose;
  425.  
  426.     image = newBitImage(MAXCOLS, MAXROWS);
  427.  
  428.     currline = image->data;
  429.     cols = 0;
  430.     for (rows = 0; rows < MAXROWS; ++rows) {
  431.         col = g3_getfaxrow(fd, currline);
  432. #ifndef ALLOW_G3_ERRORS
  433.         if (col < 0) {
  434.           freeImage(image);
  435.           zclose(fd);
  436.           return(NULL);
  437.         }
  438. #else
  439.         if (g3_error > MAX_ERRORS) {
  440.           freeImage(image);
  441.           zclose(fd);
  442.           return(NULL);
  443.           }            
  444. #endif
  445.         if (g3_eof)
  446.             break;
  447.         if (col > cols)
  448.             cols = col;
  449.         currline += BITS_TO_BYTES(cols);
  450.         }
  451.  
  452.     zclose(fd);
  453.     image->title= dupString(name);
  454.     image->width = cols;
  455.     image->height = rows;
  456.     if (!image->width || !image->height) { /* sanity check */
  457.         freeImage(image);
  458.         return(NULL);
  459.     }
  460.  
  461.     if(verbose)
  462.         printf("  %s is a %dx%d G3 FAX image.\n", name, image->width, image->height);
  463.     return(image);
  464. }
  465.  
  466. /* originally this used only g3_ident to determine if it was a G3 image, but
  467.  * it was always getting false positives so now it loads the whole image in
  468.  * to see if it's reasonable.
  469.  */
  470. int    g3Ident(fullname, name)
  471.     char    *fullname, *name;
  472. {
  473.     Image *image;
  474.  
  475.     g3_verb = 0;
  476.     if (image= g3Load(fullname, name, 1)) {
  477.         freeImage(image);
  478.         return(1);
  479.     }
  480.     return(0);
  481. }
  482.